package com.sprouting.personal.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sprouting.personal.annotations.ApiIdempotent;
import com.sprouting.personal.interfaces.common.Constant;
import com.sprouting.personal.interfaces.common.ConstantPath;
import com.sprouting.personal.model.common.ResultJson;
import com.sprouting.personal.model.common.jsr.AddGroup;
import com.sprouting.personal.model.common.jsr.UpdGroup;
import com.sprouting.personal.model.entity.Dict;
import com.sprouting.personal.model.entity.Game;
import com.sprouting.personal.service.DictService;
import com.sprouting.personal.service.GameService;
import com.sprouting.personal.utils.CheckTool;
import com.sprouting.personal.utils.EntityTool;
import com.sprouting.personal.utils.IdTool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * 游戏
 *
 * @author ：LX（长沙麓谷）
 * @date 创建时间： 2022/9/11 10:34
 */
@RequestMapping("/game")
@RestController
@Slf4j
public class GameController {

    @Autowired
    private DictService dictService;
    @Autowired
    private GameService gameService;

    /**
     * 文件存储基础路径
     */
    @Value("${upload.data.base.path}")
    private String basePath;
    /**
     * 上传图片类型
     */
    @Value("#{'${upload.image.type}'.split(',')}")
    private List<String> uploadImageTypeList;
    /**
     * 图片文件上传最大长度
     */
    @Value("${upload.image.max.length}")
    private Integer uploadImageMaxLength;


    /**
     * 分页查询游戏信息
     * @param page 分页参数
     * @param game 查询参数
     * @return
     */
    @PostMapping("/getGameListPage")
    public ResultJson getGameListPage(Page page, Game game){
        if (game == null){
            game = new Game();
        }
        game.setUserId(StpUtil.getLoginIdAsString());
        return ResultJson.success(gameService.getGameListPage(page, game));
    }


    /**
     * 物理删除游戏
     * @param id 游戏ID
     * @return
     */
    @PostMapping("/delGameById")
    @ApiIdempotent
    public ResultJson delGameById(String id){
        if (CheckTool.checkNull(id)){
            return ResultJson.errorIllegal();
        }
        Game gameDb = gameService.getGameById(id);
        if (gameDb == null){
            return ResultJson.errorPram();
        }

        // 直接物理删除
        gameService.removeById(id);

        String icoPath = gameDb.getIco();
        if (!CheckTool.checkNull(icoPath)){
            // 做容错措施，如果是目录，不进行操作，数据非常重要，一定要多检查
            if (FileUtil.isFile(basePath + icoPath)){
                FileUtil.del(basePath + icoPath);
            } else {
                log.error("要删除的是数据是目录，跳过该删除操作：{}", basePath + icoPath);
            }
        }

        return ResultJson.success(null);
    }

    /**
     * 更新游戏
     * @param game 游戏
     * @return
     */
    @PostMapping("/updGame")
    @ApiIdempotent
    public ResultJson updGame(@Validated(UpdGroup.class) Game game, @RequestParam(value = "file", required = false) MultipartFile file){
        String msg = checkGame(game);
        if (msg != null){
            return ResultJson.error(msg);
        }

        Game gameDb = gameService.getGameById(game.getId());
        if (gameDb == null){
            return ResultJson.errorPram();
        }

        if (file != null){
            String err = saveGameCover(file, game);
            if (err != null){
                return ResultJson.error(err);
            }
        }

        EntityTool.buildUpdBase(game, StpUtil.getLoginIdAsString());
        gameService.updateById(game);

        // 清理旧数据
        clearOldData(file, gameDb);

        return ResultJson.success(game);
    }


    /**
     * 保存游戏
     * @param game 游戏
     * @return
     */
    @PostMapping("/saveGame")
    public ResultJson saveGame(@Validated(AddGroup.class) Game game, @RequestParam(value = "file", required = false) MultipartFile file){
        String msg = checkGame(game);
        if (msg != null){
            return ResultJson.error(msg);
        }

        if (file != null){
            String err = saveGameCover(file, game);
            if (err != null){
                return ResultJson.error(err);
            }
        }

        game.setId(IdTool.getId());
        game.setUserId(StpUtil.getLoginIdAsString());
        EntityTool.buildSaveBase(game, StpUtil.getLoginIdAsString());
        gameService.save(game);
        return ResultJson.success(game);
    }

    /**
     * 获取游戏类型
     * @return
     */
    @PostMapping("/getGameType")
    public ResultJson<List<Dict>> getGameType(){
        List<Dict> dictList = dictService.getType(Constant.RetainDictGroup.GAME_GROUP, StpUtil.getLoginIdAsString());
        return ResultJson.success(dictList);
    }

    /**
     * 清理旧的游戏书籍信息
     * @param file 上传的游戏图片
     * @param gameDb 旧的游戏信息
     */
    private void clearOldData(MultipartFile file, Game gameDb){
        // 只有新增之后才能删除旧的，否则不去操作
        if (file != null){
            String icoPath = gameDb.getIco();
            if (!CheckTool.checkNull(icoPath)){
                // 做容错措施，如果是目录，不进行操作，数据非常重要，一定要多检查
                if (FileUtil.isFile(basePath + icoPath)){
                    FileUtil.del(basePath + icoPath);
                } else {
                    log.error("要删除的是数据是目录，跳过该删除操作：{}", basePath + icoPath);
                }
            }
        }
    }

    /**
     * 保存游戏封面
     * @param file 上传的封面文件
     * @param game 游戏信息
     * @return 非null返回，则是有错误信息
     */
    private String saveGameCover(MultipartFile file, Game game){
        String originalFilename = file.getOriginalFilename();
        if (CheckTool.checkNull(originalFilename)){
            return "获取文件名失败";
        }
        String suffix = FileUtil.getSuffix(originalFilename).toLowerCase();
        if (CheckTool.checkNull(suffix)){
            // 检查特殊情况下的文件名不符合
            return "非法上传图片名，不支持的后缀";
        }
        if (uploadImageTypeList != null){
            if (!uploadImageTypeList.contains(suffix)){
                return "上传图片类型不支持";
            }
        }
        if (file.getSize() > uploadImageMaxLength){
            return "上传图片超过限定大小";
        }

        String path = String.format(ConstantPath.Path.GAME_ICO, basePath, StpUtil.getLoginIdAsString(), IdTool.getId(), suffix);
        File toFile = new File(path);
        // 上传路径
        if (!FileUtil.exist(toFile)){
            FileUtil.touch(toFile);
        }

        try {
            file.transferTo(toFile);
        } catch (IOException e) {
            log.error("图片上传失败", e);
            return "图片上传失败";
        }

        // 只保存相对路径
        String replacePath = path.replace(basePath, "");
        game.setIco(replacePath);
        return null;
    }

    /**
     * 游戏信息校验
     * @param game 游戏信息
     * @return 返回非null都是有问题的
     */
    private String checkGame(Game game){
        Game gameDb = gameService.getGameRepeatQuery(game.getId(), StpUtil.getLoginIdAsString(), game.getName(), game.getManufacturer());
        if (gameDb != null){
            return "该游戏已入库，不需要重复录入";
        }

        return null;
    }
}
